//
// Created by 29019 on 2020/4/18.
//
#pragma once

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0500
#endif


#ifdef linux
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#define EVENT__HAVE_PTHREADS
#endif

extern  "C"{
    #include "event2/bufferevent.h"
    #include "event2/bufferevent_struct.h"
    #include "event2/buffer.h"
    #include "event2/listener.h"
    #include "event2/util.h"
    #include "event2/event.h"
    #include "event2/thread.h"
	/* For int types. */
    #include <event2/util.h>
    /* For struct event */
    #include <event2/event_struct.h>

};

#include<string.h>
#include <iostream>
#include <mutex>
#include <thread>
#include <functional>

using  namespace std;

class TcpClientLibevent {
public:
    typedef enum {
        UNCONNECTED,  // 未连接
		CONNECTING, //已经连接
        CONNECTED, //已经连接
        FAIL,       // 连接失败
        STOP,      // 初始状态
    }Status;

    class TcpClientObserver {
    public:
        virtual ~TcpClientObserver() { return; }
        mutex mMux;
        virtual void OnConnected() { return; };
        virtual void OnDisConnected(std::string) { return; };
        virtual void OnData(uint8_t* dat, uint64_t len) { return; };
        virtual void OnClose() { return; };
    };
    TcpClientLibevent(std::string addrinfo, int port, TcpClientObserver* p);
    ~TcpClientLibevent() {
        mMux.lock();
        mStatus = TcpClientLibevent::STOP;
		mMux.unlock();

        struct timeval tv;
        tv.tv_sec = 0;
        tv.tv_usec = 10000;
        event_base_loopexit(mBase,&tv);
        mThread->join();
        std::cout << "12345\r\n";
    };
	friend  void conn_eventcb(struct bufferevent*, short, void*);
    int ConnectServer();
	int ConnectServerSync();

    bool Connected();
    int Dispatch();
    int OnTCPPackage(uint8_t*, uint16_t);
    int SetReconnect(bool);
    int SetObserver(TcpClientObserver*);
    int Close();
    int SendDataAsync(const char*, int len);
    uint64_t SocketFd();

    Status mStatus;
    TcpClientObserver* mObserver;
private:
    bool mReConnect = false;
    int sendData(void*, size_t);
    struct event_base* mBase;
    struct bufferevent* mBev;
    struct sockaddr_in mSrv;
    std::thread* mThread;
    mutex mLock;          // 互斥锁
    uint64_t mByteSend;   // 发送字节数
    uint64_t mByteRecv;   // 接收字节数
    evutil_socket_t mSocketFD;   // 操作系统原生socket
	mutex mMux;

};


